﻿using Biomedica.Graphics;
using Microsoft.Kinect;
using SkeletonRecorder.Kinect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;

namespace NuiDicomPlayer.Nui.NavigationEngine
{
    
    public delegate void TriggerAction(NuiDicomPlayer.Nui.NavigationEngine.NuiNavigator.SkeletonsStateFlags flags);


    public class NuiNavigator : FrameworkElement
    {

        public NuiNavigator()
        {
            stateFlags = new SkeletonsStateFlags();
        }

        /// <summary>
        /// Flags are set indecating the condtion and state of the skeleton
        /// </summary>
        public class SkeletonsStateFlags
        {
            public Boolean IsSkeletonStable { set; get; }
            public Boolean IsRightHandStable { set; get; }
            public Boolean IsLeftHandStable { set; get; }
            public Boolean IsRightHandAndLeftDistnce { set; get; }
            public bool IsSkeletonInStage { get; set; }
            public Boolean IsBoothHandInSpace { get; set; }
            
            public Vector3 LeftHandMotionState { set; get; }
            public Vector3 RightHandMotionState { set; get; }
        }
        /// <summary>
        /// Trigger the MainWindow to Perform Action based on the SkeletonStatusFlags and Values
        /// </summary>
        public TriggerAction OnTriggerAction { set; get; }

        #region Singleton Initator
        private static NuiNavigator nuiNavigator;
        public static NuiNavigator New()
        {
            if (nuiNavigator == null) nuiNavigator = new NuiNavigator();
            return nuiNavigator;
        }
        #endregion
        #region Flags
        private SkeletonsStateFlags stateFlags;
        public SkeletonsStateFlags StateFlags
        {
            get
            {
                if (stateFlags == null) stateFlags = new SkeletonsStateFlags();
                return stateFlags;
            }
        }
       
        #endregion
        #region Parameters
        public  bool Enabled { get; set; }
        #endregion
        #region Detectors
        SkeletonStabilityDetector Stability_detector=new SkeletonStabilityDetector();
        SkeletonPostionDetector Stage_detector=new SkeletonPostionDetector();
        SholderJointOrantation sholder_direction_detector = new SholderJointOrantation();

        JointStabilityDetector left_hand_stable = new JointStabilityDetector();
        JointStabilityDetector right_hand_stable = new JointStabilityDetector();

        BothHandsBetweenHeadAndSpineDetector both_hands_space_detector = new BothHandsBetweenHeadAndSpineDetector();

        RighHandMotionDetector right_hand_motion_detector = new RighHandMotionDetector();
        LeftHandMotionDetector left_hand_motion_detector = new LeftHandMotionDetector();
        private Gestures.GesturPostureEngine sPEng;

        #endregion
       

        /// <summary>
        /// Start the threads to Detect Gestures
        /// </summary>
        public void StartPostureDetectionCycle()
        {
            

            // Non Task Flags
          
                sholder_direction_detector.GetSholderDirection();

                //Tasks flags
                DetectSkeletonStability();         // Detect if the Skeleton Hand is Stable
                DetectSkeletonInStage();           // Detect if the Skeleton Hand is Stable
                DetectHandStability();             // Detect if the Skeleton Hand is Stable
                DetectBothHandsInSpace();          // Detect if the Skeleton Hand is Stable
              
                if (this.OnTriggerAction != null) this.OnTriggerAction(stateFlags);
            
          
        }
      
        #region Detection Function
        /// <summary>
        /// Detect Both Hands in Space
        /// </summary>
        private void DetectBothHandsInSpace()
        {
            stateFlags.IsBoothHandInSpace = both_hands_space_detector.IsDetected(sPEng.GPBuffer.ToArray());
        }

        /// <summary>
        /// Detect hand Stability
        /// </summary>
        private void DetectHandStability()
        {

            if (stateFlags.IsLeftHandStable = left_hand_stable.IsSkeletonStable(JointType.HandLeft, sPEng.GPBuffer.ToArray()))
            {
                left_hand_motion_detector.SetReferanceJoint(JointType.HandLeft, sPEng.GPBuffer.ToArray());
            }

            if (stateFlags.IsRightHandStable = right_hand_stable.IsSkeletonStable(JointType.HandRight, sPEng.GPBuffer.ToArray()))
            {
                right_hand_motion_detector.SetReferanceJoint(JointType.HandRight, sPEng.GPBuffer.ToArray());
            }
          

           
        }
       
        /// <summary>
        /// Detect if The Skeleton is Stable
        /// </summary>
        private void DetectSkeletonStability()
        {
            if (this.stateFlags!=null)
                this.stateFlags.IsSkeletonStable = Stability_detector.IsSkeletonStable(sPEng.GPBuffer.ToArray());
        }
        /// <summary>
        /// Detect if Skeleton In Stage
        ///</summary>
        private void DetectSkeletonInStage()
        {
            this.stateFlags.IsSkeletonInStage = Stage_detector.IsSkeletonInstage(sPEng.GPBuffer.ToArray());
        }

        /// <summary>
        /// Stop The Gesture Recognition Cycle
        /// </summary>
        public void StopGestureAndPostureDetectionCycle()
        {
            Enabled = false;
        }
       
        #endregion
       
        internal void StartPostureDetectionCycle(Gestures.GesturPostureEngine eng)
        {
            this.sPEng = eng;
            StartPostureDetectionCycle();
        }
    }
}
